# 使用条件实现线程同步
import logging
import threading
import time

LOG_FORMAT = '%(asctime)s %(threadName)-17s %(levelname)-8s %(message)s'
logging.basicConfig(level=logging.INFO, format=LOG_FORMAT)
items = []
condition = threading.Condition()


class Consumer(threading.Thread):  # 这里其实是consumer类继承了threading.Thread类
    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)  # 这样执行超类，才可以访问超类的参数

    def consume(self):
        with condition:
            if len(items) == 0:
                logging.info('no items to consume')
                condition.wait()
            else:
                items.pop()
                logging.info('consume 1 item')
                condition.notify()

    def run(self):
        for i in range(20):
            time.sleep(2)  # 消费的时间，如果消费时间小于生产时间，那么只会生产一个立马消费一个
            self.consume()


class Producer(threading.Thread):
    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)  # 这样执行超类，才可以访问超类的参数

    def produce(self):
        with condition:
            if len(items) == 10:  # 如果满了20个，那么就会挂掉，直到另外一个线程notify，这个线程才会继续。
                logging.info('items produced {}. Stopped!'.format(len(items)))
                condition.wait()
            else:
                items.append(1)
                logging.info('total items {}.'.format(len(items)))
                condition.notify()

    def run(self):
        for i in range(20):  # 会尝试生产20次
            time.sleep(1)
            self.produce()


def main():
    producer = Producer(name='Producer')
    consumer = Consumer(name='Consumer')

    producer.start()
    consumer.start()

    producer.join()
    consumer.join()


if __name__ == '__main__':
    main()
